layerSceneComponent.ts 5.7 KB

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