effectLayerSceneComponent.js 8.1 KB

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