layerSceneComponent.ts 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. import { Camera } from "../Cameras/camera";
  2. import { Scene } from "../scene";
  3. import { Engine } from "../Engines/engine";
  4. import { SceneComponentConstants, ISceneComponent } from "../sceneComponent";
  5. import { Layer } from "./layer";
  6. import { RenderTargetTexture } from "../Materials/Textures/renderTargetTexture";
  7. import { AbstractScene } from '../abstractScene';
  8. declare module "../abstractScene" {
  9. export interface AbstractScene {
  10. /**
  11. * The list of layers (background and foreground) of the scene
  12. */
  13. layers: Array<Layer>;
  14. }
  15. }
  16. /**
  17. * Defines the layer scene component responsible to manage any layers
  18. * in a given scene.
  19. */
  20. export class LayerSceneComponent implements ISceneComponent {
  21. /**
  22. * The component name helpfull to identify the component in the list of scene components.
  23. */
  24. public readonly name = SceneComponentConstants.NAME_LAYER;
  25. /**
  26. * The scene the component belongs to.
  27. */
  28. public scene: Scene;
  29. private _engine: Engine;
  30. /**
  31. * Creates a new instance of the component for the given scene
  32. * @param scene Defines the scene to register the component in
  33. */
  34. constructor(scene: Scene) {
  35. this.scene = scene;
  36. this._engine = scene.getEngine();
  37. scene.layers = new Array<Layer>();
  38. }
  39. /**
  40. * Registers the component in a given scene
  41. */
  42. public register(): void {
  43. this.scene._beforeCameraDrawStage.registerStep(SceneComponentConstants.STEP_BEFORECAMERADRAW_LAYER, this, this._drawCameraBackground);
  44. this.scene._afterCameraDrawStage.registerStep(SceneComponentConstants.STEP_AFTERCAMERADRAW_LAYER, this, this._drawCameraForeground);
  45. this.scene._beforeRenderTargetDrawStage.registerStep(SceneComponentConstants.STEP_BEFORERENDERTARGETDRAW_LAYER, this, this._drawRenderTargetBackground);
  46. this.scene._afterRenderTargetDrawStage.registerStep(SceneComponentConstants.STEP_AFTERRENDERTARGETDRAW_LAYER, this, this._drawRenderTargetForeground);
  47. }
  48. /**
  49. * Rebuilds the elements related to this component in case of
  50. * context lost for instance.
  51. */
  52. public rebuild(): void {
  53. let layers = this.scene.layers;
  54. for (let layer of layers) {
  55. layer._rebuild();
  56. }
  57. }
  58. /**
  59. * Disposes the component and the associated ressources.
  60. */
  61. public dispose(): void {
  62. let layers = this.scene.layers;
  63. while (layers.length) {
  64. layers[0].dispose();
  65. }
  66. }
  67. private _draw(predicate: (layer: Layer) => boolean): void {
  68. let layers = this.scene.layers;
  69. if (layers.length) {
  70. this._engine.setDepthBuffer(false);
  71. for (let layer of layers) {
  72. if (predicate(layer)) {
  73. layer.render();
  74. }
  75. }
  76. this._engine.setDepthBuffer(true);
  77. }
  78. }
  79. private _drawCameraPredicate(layer: Layer, isBackground: boolean, cameraLayerMask: number): boolean {
  80. return !layer.renderOnlyInRenderTargetTextures &&
  81. layer.isBackground === isBackground &&
  82. ((layer.layerMask & cameraLayerMask) !== 0);
  83. }
  84. private _drawCameraBackground(camera: Camera): void {
  85. this._draw((layer: Layer) => {
  86. return this._drawCameraPredicate(layer, true, camera.layerMask);
  87. });
  88. }
  89. private _drawCameraForeground(camera: Camera): void {
  90. this._draw((layer: Layer) => {
  91. return this._drawCameraPredicate(layer, false, camera.layerMask);
  92. });
  93. }
  94. private _drawRenderTargetPredicate(layer: Layer, isBackground: boolean, cameraLayerMask: number, renderTargetTexture: RenderTargetTexture): boolean {
  95. return (layer.renderTargetTextures.length > 0) &&
  96. layer.isBackground === isBackground &&
  97. (layer.renderTargetTextures.indexOf(renderTargetTexture) > -1) &&
  98. ((layer.layerMask & cameraLayerMask) !== 0);
  99. }
  100. private _drawRenderTargetBackground(renderTarget: RenderTargetTexture): void {
  101. this._draw((layer: Layer) => {
  102. return this._drawRenderTargetPredicate(layer, true, this.scene.activeCamera!.layerMask, renderTarget);
  103. });
  104. }
  105. private _drawRenderTargetForeground(renderTarget: RenderTargetTexture): void {
  106. this._draw((layer: Layer) => {
  107. return this._drawRenderTargetPredicate(layer, false, this.scene.activeCamera!.layerMask, renderTarget);
  108. });
  109. }
  110. /**
  111. * Adds all the elements from the container to the scene
  112. * @param container the container holding the elements
  113. */
  114. public addFromContainer(container: AbstractScene): void {
  115. if (!container.layers) {
  116. return;
  117. }
  118. container.layers.forEach((layer) => {
  119. this.scene.layers.push(layer);
  120. });
  121. }
  122. /**
  123. * Removes all the elements in the container from the scene
  124. * @param container contains the elements to remove
  125. * @param dispose if the removed element should be disposed (default: false)
  126. */
  127. public removeFromContainer(container: AbstractScene, dispose = false): void {
  128. if (!container.layers) {
  129. return;
  130. }
  131. container.layers.forEach((layer) => {
  132. var index = this.scene.layers.indexOf(layer);
  133. if (index !== -1) {
  134. this.scene.layers.splice(index, 1);
  135. }
  136. if (dispose) {
  137. layer.dispose();
  138. }
  139. });
  140. }
  141. }