layerSceneComponent.ts 5.6 KB

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