prePassRendererSceneComponent.ts 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import { Nullable } from "../types";
  2. import { Scene } from "../scene";
  3. import { ISceneComponent, SceneComponentConstants } from "../sceneComponent";
  4. import { PrePassRenderer } from "./prePassRenderer";
  5. import { Logger } from "../Misc/logger";
  6. import { AbstractMesh } from "../Meshes/abstractMesh";
  7. import { SubMesh } from "../Meshes/subMesh";
  8. import { _InstancesBatch } from "../Meshes/mesh";
  9. import { Effect } from "../Materials/effect";
  10. import { Camera } from '../Cameras/camera';
  11. declare module "../abstractScene" {
  12. export interface AbstractScene {
  13. /** @hidden (Backing field) */
  14. _prePassRenderer: Nullable<PrePassRenderer>;
  15. /**
  16. * Gets or Sets the current prepass renderer associated to the scene.
  17. */
  18. prePassRenderer: Nullable<PrePassRenderer>;
  19. /**
  20. * Enables the prepass and associates it with the scene
  21. * @returns the PrePassRenderer
  22. */
  23. enablePrePassRenderer(): Nullable<PrePassRenderer>;
  24. /**
  25. * Disables the prepass associated with the scene
  26. */
  27. disablePrePassRenderer(): void;
  28. }
  29. }
  30. Object.defineProperty(Scene.prototype, "prePassRenderer", {
  31. get: function(this: Scene) {
  32. return this._prePassRenderer;
  33. },
  34. set: function(this: Scene, value: Nullable<PrePassRenderer>) {
  35. if (value && value.isSupported) {
  36. this._prePassRenderer = value;
  37. }
  38. },
  39. enumerable: true,
  40. configurable: true
  41. });
  42. Scene.prototype.enablePrePassRenderer = function(): Nullable<PrePassRenderer> {
  43. if (this._prePassRenderer) {
  44. return this._prePassRenderer;
  45. }
  46. this._prePassRenderer = new PrePassRenderer(this);
  47. if (!this._prePassRenderer.isSupported) {
  48. this._prePassRenderer = null;
  49. Logger.Error("PrePassRenderer needs WebGL 2 support.\n" +
  50. "Maybe you tried to use the following features that need the PrePassRenderer :\n" +
  51. " + Subsurface Scattering");
  52. }
  53. return this._prePassRenderer;
  54. };
  55. Scene.prototype.disablePrePassRenderer = function(): void {
  56. if (!this._prePassRenderer) {
  57. return;
  58. }
  59. this._prePassRenderer.dispose();
  60. this._prePassRenderer = null;
  61. };
  62. /**
  63. * Defines the Geometry Buffer scene component responsible to manage a G-Buffer useful
  64. * in several rendering techniques.
  65. */
  66. export class PrePassRendererSceneComponent implements ISceneComponent {
  67. /**
  68. * The component name helpful to identify the component in the list of scene components.
  69. */
  70. public readonly name = SceneComponentConstants.NAME_PREPASSRENDERER;
  71. /**
  72. * The scene the component belongs to.
  73. */
  74. public scene: Scene;
  75. /**
  76. * Creates a new instance of the component for the given scene
  77. * @param scene Defines the scene to register the component in
  78. */
  79. constructor(scene: Scene) {
  80. this.scene = scene;
  81. }
  82. /**
  83. * Registers the component in a given scene
  84. */
  85. public register(): void {
  86. this.scene._beforeCameraDrawStage.registerStep(SceneComponentConstants.STEP_BEFORECAMERADRAW_PREPASS, this, this._beforeCameraDraw);
  87. this.scene._afterCameraDrawStage.registerStep(SceneComponentConstants.STEP_AFTERCAMERADRAW_PREPASS, this, this._afterCameraDraw);
  88. this.scene._beforeClearStage.registerStep(SceneComponentConstants.STEP_BEFORECLEARSTAGE_PREPASS, this, this._beforeClearStage);
  89. this.scene._beforeRenderingMeshStage.registerStep(SceneComponentConstants.STEP_BEFORERENDERINGMESH_PREPASS, this, this._beforeRenderingMeshStage);
  90. this.scene._afterRenderingMeshStage.registerStep(SceneComponentConstants.STEP_AFTERRENDERINGMESH_PREPASS, this, this._afterRenderingMeshStage);
  91. }
  92. private _beforeCameraDraw(camera: Camera) {
  93. if (this.scene.prePassRenderer) {
  94. this.scene.prePassRenderer._beforeCameraDraw(camera);
  95. }
  96. }
  97. private _afterCameraDraw(camera: Camera) {
  98. if (this.scene.prePassRenderer) {
  99. this.scene.prePassRenderer._afterCameraDraw(camera);
  100. }
  101. }
  102. private _beforeClearStage() {
  103. if (this.scene.prePassRenderer) {
  104. this.scene.prePassRenderer.clear();
  105. }
  106. }
  107. private _beforeRenderingMeshStage(mesh: AbstractMesh, subMesh: SubMesh, batch: _InstancesBatch, effect: Nullable<Effect>) {
  108. if (!effect) {
  109. return;
  110. }
  111. // Render to MRT
  112. const scene = mesh.getScene();
  113. if (scene.prePassRenderer) {
  114. scene.prePassRenderer.bindAttachmentsForEffect(effect, subMesh);
  115. }
  116. }
  117. private _afterRenderingMeshStage(mesh: AbstractMesh) {
  118. const scene = mesh.getScene();
  119. if (scene.prePassRenderer) {
  120. scene.prePassRenderer.restoreAttachments();
  121. }
  122. }
  123. /**
  124. * Rebuilds the elements related to this component in case of
  125. * context lost for instance.
  126. */
  127. public rebuild(): void {
  128. // Nothing to do for this component
  129. }
  130. /**
  131. * Disposes the component and the associated ressources
  132. */
  133. public dispose(): void {
  134. // Nothing to do for this component
  135. }
  136. }
  137. PrePassRenderer._SceneComponentInitialization = (scene: Scene) => {
  138. // Register the G Buffer component to the scene.
  139. let component = scene._getComponent(SceneComponentConstants.NAME_PREPASSRENDERER) as PrePassRendererSceneComponent;
  140. if (!component) {
  141. component = new PrePassRendererSceneComponent(scene);
  142. scene._addComponent(component);
  143. }
  144. };