babylon.effectLayerSceneComponent.ts 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. module BABYLON {
  2. // Adds the parser to the scene parsers.
  3. AbstractScene.AddParser(SceneComponentConstants.NAME_EFFECTLAYER, (parsedData: any, scene: Scene, container: AssetContainer, rootUrl: string) => {
  4. if (parsedData.effectLayers) {
  5. for (let index = 0; index < parsedData.effectLayers.length; index++) {
  6. var effectLayer = EffectLayer.Parse(parsedData.effectLayers[index], scene, rootUrl);
  7. container.effectLayers.push(effectLayer);
  8. }
  9. }
  10. });
  11. export interface AbstractScene {
  12. /**
  13. * The list of effect layers (highlights/glow) added to the scene
  14. * @see http://doc.babylonjs.com/how_to/highlight_layer
  15. * @see http://doc.babylonjs.com/how_to/glow_layer
  16. */
  17. effectLayers: Array<EffectLayer>;
  18. /**
  19. * Removes the given effect layer from this scene.
  20. * @param toRemove defines the effect layer to remove
  21. * @returns the index of the removed effect layer
  22. */
  23. removeEffectLayer(toRemove: EffectLayer): number;
  24. /**
  25. * Adds the given effect layer to this scene
  26. * @param newEffectLayer defines the effect layer to add
  27. */
  28. addEffectLayer(newEffectLayer: EffectLayer): void;
  29. }
  30. AbstractScene.prototype.removeEffectLayer = function(toRemove: EffectLayer): number {
  31. var index = this.effectLayers.indexOf(toRemove);
  32. if (index !== -1) {
  33. this.effectLayers.splice(index, 1);
  34. }
  35. return index;
  36. }
  37. AbstractScene.prototype.addEffectLayer = function(newEffectLayer: EffectLayer): void {
  38. this.effectLayers.push(newEffectLayer);
  39. }
  40. /**
  41. * Defines the layer scene component responsible to manage any effect layers
  42. * in a given scene.
  43. */
  44. export class EffectLayerSceneComponent implements ISceneSerializableComponent {
  45. /**
  46. * The component name helpfull to identify the component in the list of scene components.
  47. */
  48. public readonly name = SceneComponentConstants.NAME_EFFECTLAYER;
  49. /**
  50. * The scene the component belongs to.
  51. */
  52. public scene: Scene
  53. private _engine: Engine;
  54. private _renderEffects = false;
  55. private _needStencil = false;
  56. private _previousStencilState = false;
  57. /**
  58. * Creates a new instance of the component for the given scene
  59. * @param scene Defines the scene to register the component in
  60. */
  61. constructor(scene: Scene) {
  62. this.scene = scene;
  63. this._engine = scene.getEngine();
  64. scene.effectLayers = new Array<EffectLayer>();
  65. }
  66. /**
  67. * Registers the component in a given scene
  68. */
  69. public register(): void {
  70. this.scene._isReadyForMeshStage.registerStep(SceneComponentConstants.STEP_ISREADYFORMESH_EFFECTLAYER, this, this._isReadyForMesh);
  71. this.scene._cameraDrawRenderTargetStage.registerStep(SceneComponentConstants.STEP_CAMERADRAWRENDERTARGET_EFFECTLAYER, this, this._renderMainTexture);
  72. this.scene._beforeCameraDrawStage.registerStep(SceneComponentConstants.STEP_BEFORECAMERADRAW_EFFECTLAYER, this, this._setStencil);
  73. this.scene._afterRenderingGroupDrawStage.registerStep(SceneComponentConstants.STEP_AFTERRENDERINGGROUPDRAW_EFFECTLAYER_DRAW, this, this._drawRenderingGroup);
  74. this.scene._afterCameraDrawStage.registerStep(SceneComponentConstants.STEP_AFTERCAMERADRAW_EFFECTLAYER, this, this._setStencilBack);
  75. this.scene._afterCameraDrawStage.registerStep(SceneComponentConstants.STEP_AFTERCAMERADRAW_EFFECTLAYER_DRAW, this, this._drawCamera);
  76. }
  77. /**
  78. * Rebuilds the elements related to this component in case of
  79. * context lost for instance.
  80. */
  81. public rebuild(): void {
  82. let layers = this.scene.effectLayers;
  83. for (let effectLayer of layers) {
  84. effectLayer._rebuild();
  85. }
  86. }
  87. /**
  88. * Serializes the component data to the specified json object
  89. * @param serializationObject The object to serialize to
  90. */
  91. public serialize(serializationObject: any): void {
  92. // Effect layers
  93. serializationObject.effectLayers = [];
  94. let layers = this.scene.effectLayers;
  95. for (let effectLayer of layers) {
  96. if (effectLayer.serialize) {
  97. serializationObject.effectLayers.push(effectLayer.serialize());
  98. }
  99. }
  100. }
  101. /**
  102. * Adds all the element from the container to the scene
  103. * @param container the container holding the elements
  104. */
  105. public addFromContainer(container: AbstractScene): void {
  106. if (!container.effectLayers) {
  107. return;
  108. }
  109. container.effectLayers.forEach((o) => {
  110. this.scene.addEffectLayer(o);
  111. });
  112. }
  113. /**
  114. * Removes all the elements in the container from the scene
  115. * @param container contains the elements to remove
  116. */
  117. public removeFromContainer(container: AbstractScene): void {
  118. if (!container.effectLayers) {
  119. return;
  120. }
  121. container.effectLayers.forEach((o) => {
  122. this.scene.removeEffectLayer(o);
  123. });
  124. }
  125. /**
  126. * Disposes the component and the associated ressources.
  127. */
  128. public dispose(): void {
  129. let layers = this.scene.effectLayers;
  130. while (layers.length) {
  131. layers[0].dispose();
  132. }
  133. }
  134. private _isReadyForMesh(mesh: AbstractMesh, hardwareInstancedRendering: boolean): boolean {
  135. let layers = this.scene.effectLayers;
  136. for (let layer of layers) {
  137. if (!layer.hasMesh(mesh)) {
  138. continue;
  139. }
  140. for (var subMesh of mesh.subMeshes) {
  141. if (!layer.isReady(subMesh, hardwareInstancedRendering)) {
  142. return false;
  143. }
  144. }
  145. }
  146. return true;
  147. }
  148. private _renderMainTexture(camera: Camera): void {
  149. this._renderEffects = false;
  150. this._needStencil = false;
  151. let layers = this.scene.effectLayers;
  152. if (layers && layers.length > 0) {
  153. this._previousStencilState = this._engine.getStencilBuffer();
  154. for (let effectLayer of layers) {
  155. if (effectLayer.shouldRender() &&
  156. (!effectLayer.camera ||
  157. (effectLayer.camera.cameraRigMode === Camera.RIG_MODE_NONE && camera === effectLayer.camera) ||
  158. (effectLayer.camera.cameraRigMode !== Camera.RIG_MODE_NONE && effectLayer.camera._rigCameras.indexOf(camera) > -1))) {
  159. this._renderEffects = true;
  160. this._needStencil = this._needStencil || effectLayer.needStencil();
  161. let renderTarget = (<RenderTargetTexture>(<any>effectLayer)._mainTexture);
  162. if (renderTarget._shouldRender()) {
  163. this.scene.incrementRenderId();
  164. renderTarget.render(false, false);
  165. }
  166. }
  167. }
  168. this.scene.incrementRenderId();
  169. }
  170. }
  171. private _setStencil(camera: Camera) {
  172. // Activate effect Layer stencil
  173. if (this._needStencil) {
  174. this._engine.setStencilBuffer(true);
  175. }
  176. }
  177. private _setStencilBack(camera: Camera) {
  178. // Restore effect Layer stencil
  179. if (this._needStencil) {
  180. this._engine.setStencilBuffer(this._previousStencilState);
  181. }
  182. }
  183. private _draw(renderingGroupId: number): void {
  184. if (this._renderEffects) {
  185. this._engine.setDepthBuffer(false);
  186. let layers = this.scene.effectLayers;
  187. for (let i = 0; i < layers.length; i++) {
  188. const effectLayer = layers[i];
  189. if (effectLayer.renderingGroupId === renderingGroupId) {
  190. if (effectLayer.shouldRender()) {
  191. effectLayer.render();
  192. }
  193. }
  194. }
  195. this._engine.setDepthBuffer(true);
  196. }
  197. }
  198. private _drawCamera(camera: Camera): void {
  199. if (this._renderEffects) {
  200. this._draw(-1);
  201. }
  202. }
  203. private _drawRenderingGroup(index: number): void {
  204. if (!this.scene._isInIntermediateRendering() && this._renderEffects) {
  205. this._draw(index);
  206. }
  207. }
  208. }
  209. }